자바스크립트 정규표현식
자바스크립트 정규표현식

코드를 짜다보면 전화번호, 이메일 등의 체크 형식에서 정규표현식을 종종 사용하는 경우가 있는 데, 한눈에 봤을 때 코드를 이해하기 어려운 경우가 종종있었다. 어떤 방식으로 정규표현식을 작성하는지 알아보기 위해 공부해보았다.
정규표현식
정규 표현식(regular expression)은 문자 검색과 교체에 사용되는 패턴이다. 자바스크립트에서는 RegExp 객체와 문자열 메서드를 조합하여 정규표현식을 사용할 수 있다.
-
정규 표현식은 패턴과 선택적으로 사용할 수 있는 플래그로 구성된다.
-
정규식 객체를 만들 때는 두 가지 문법이 사용된다.
- 긴 문법
- 긴 문법은 아래와 같이 사용한다.
regexp = new RegExp('pattern', 'flags');- 짧은 문법
- 짧은 문법은
/를 사용한다.
- 짧은 문법은
regexp = /pattern/; // 플래그가 없음 regexp = /pattern/gim; // 플래그 g, m, i 가 있음 - 긴 문법
-
/는 자바스크립트에 정규 표현식을 생성하고 있다는 것을 알린다. 문자열에 따옴표를 쓰는 것과 동일한 역할 -
짧은 문법이든 긴 문법이든 상관없이
regexp는 내장 클래스RegExp의 인스턴스가 된다. -
단, 두 문법의 차이점은
/…/를 사용하면 문자열 템플릿 리터럴에서${…}를 사용했던 것처럼 중간에 표현식을 넣을 수 없다. 슬래시를 사용한 방법은 완전히 정적이기 때문이다. -
짧은 문법을 사용할 때는 코드를 작성하는 시점에 패턴을 알고 있을 때 사용한다. 반면 긴 문법은 상황에 따라 동적으로 생성된 문자열을 가지고 정규 표현식을 만들어야 할 때 주로 사용한다.
let tag = prompt('어떤 태그를 찾고 싶은가요?', 'h2');
let regexp = new RegExp(`<${tag}>`); // 프롬프트에서 'h2'라고 대답한 경우, /<h2>/와 동일한 역할을 한다.플래그
- 정규 표현식에는 검색에 영향을 주는 플래그를 선택적으로 붙일 수 있다.
- 자바스크립트에서는 6개의 플래그를 지원한다.
pattern:i: i플래그가 붙으면 대소문자 구분없이 검색한다. Ignore casepattern:g: g플래그가 붙으면 패턴과 일치하는 모든 것들을 찾는다. g가 없으면 패턴과 일치하는 첫 번째 결과만 반환된다. Globalpattern:m: 다중 행 모드(multiline mode)를 활성화한다.(여러행 검색)pattern:s:pattern:.이 개행문자\n도 포함하도록 dotail 모드를 활성화한다.pattern:u: 유니코드 전체를 지원한다. 이 플래그를 사용하면 서로게이트 쌍을 올바르게 처리할 수 있다.pattern:y: 문자 내 특정 위치에서 검색을 진행하는 sticky 모드를 활성화 시킨다.
str.match로 검색하기
str.match(regexp)에는 3가지 모드가 있다.
- 정규 표현식에 플래그
pattern:g가 붙으면 패턴과 일치하는 모든 것을 담은 배열을 반환
let str = 'We will, we will rock you';
alert(str.match(/we/gi)); // We, we
/**
* g : 패턴과 일치하는 모든것
* i : 대소문자 구분 없음
* /- 플래그
pattern:g가 붙지 않은 경우에는 패턴에 맞는 첫 번째 부분 문자열만 담은 배열을 반환. 해당 문자열은 배열 인덱스 0에 저장되는데, 문자열의 프로퍼티에는 상세한 추가 정보가 저장된다.
let str = 'We will, we will rock you';
let result = str.match(/we/i);
alert(result[0]); // We
alert(result.length); // 1
alert(result.index); // 0 (부분 문자열의 위치)
alert(result.input); // We will, we will rock you (원본문자열 )- 정규 표현식을 괄호로 둘러싼 경우에는 메서드 호출 시 반환되는 배열에 0이외에도 다른 인덱스가 있을 수 있음
pattern:g의 유무와 상관없이 패턴과 일치하는 부분 문자열을 찾지 못한 경우에는null이 반환된다.
let matches = 'JavaScript'.match(/HTML/); // matches에는 null이 저장
if (!matches.length) {
// TypeError
//code
}str.match호출 결과가 항상 배열이 되게 하려면 아래와 같이 사용한다.
let matches = 'JavaScript'.match(/HTML/) || [];
if (!matches.legnth) {
alert('정규 표현식과 일치하는 부분 문자열이 없다.');
}str.replace로 치환
str.replace(regexp, replacement)를 사용하면 regexp에 일치하는 부분 문자열을 replacement로 교체할 수 있다.
console.log('We will, we will'.replace(/we/i, 'I')); // I will, we will-
replacement는 문자열인데, 문자열 안에 아래 특수문자를 넣으면 독특한 방식으로 문자열을 교체할 수 있다. -
$&: 패턴과 일치하는 부분 문자열 -
$`: 문자열 일부를 일치 전에 삽입 -
$’: 문자열 일부를 일치 후에 삽입 -
$n: n이 1~2자리 숫자일 경우, n번째 괄호 내용을 삽입 -
$$: $문자를 삽입
regexp.test로 일치 여부 확인하기
- 패턴과 일치하는 부분 문자열이 하나라도 있는경우 true, 아니면 false를 반환한다.
let str = 'I love JavaScript';
let regexp = /LOVE/i;
alert(regexp.test(str)); // true문자클래스
-
문자 클래스는 특정 집합에 포함된 모든 기호에 일치하는 특별한 표현이다.
-
문자 클래스에는 다음과 같은 클래스가 있다.
-
pattern:\d: 숫자 -
pattern:\D: 숫자가 아닌 문자 -
pattern:\s: 스페이스, 탭, 줄 바꿈 문자 -
pattern:\S: 스페이스, 탭, 줄바꿈문자를 제외한 모든 문자 -
pattern:\w: 라틴문자, 숫자, 밑줄_ -
pattern:\W: 라틴문자, 숫자, 밑줄을 제외한 모든 문자 -
pattern:.: 정규표현식’s’플래그가 있으면 모든 문자, 없으면 줄바꿈을 제외한 모든 문자
let str = '+7(903)-123-45-67';
let regexp = /\d/;
alert(str.match(regexp)); // 7 , 가장 먼저 만난 숫자가 7
let regexp2 = /\d/g;
console.log(str.match(regexp2)); //['7', '9', '0', '3', '1', '2', '3', '4', '5', '6', '7']
console.log(str.match(regexp).join('')); // 79035419441- 정규 표현식에 일반 기호와 문자 클래스를 같이 사용할 수 있다.
let str = 'Is there CSS4?';
let regexp = /CSS\d/;
console.log(str.match(regexp)); // CSS4- 문자 클래스를 여러개 사용할 수도 있다.
console.log('I love HTML5'.match(/\s\w\w\w\w\d/)); // 'HTML5'반대 클래스
- 모든 문자 클래스에는 반대클래스가 있다. 같은 글자로 표기하지만 대문자를 사용한다.
- 반대란 해당 문자를 제외한 모든 문자에 일치한다.
- 패턴 d,D / 패턴 s,S / 패턴 w,W
let str = '+7(903)-123-45-67';
alert(str.replace(/\D/g, '')); // 숫자가 아닌 문자를 찾아 문자열에서 없애버리는 것점은 아무문자에나 일치
pattern : .은 줄 바꿈 문자를 제외한 모든 문자와 일치하는 특별한 문자 클래스이다.
alert('Z'.match(/./)); // Z
let regexp = /CS.4/;
alert('CSS4'.match(regexp)); // CSS4
alert('CS 4'.match(regexp)); // CS 4 (공백도 문자이기때문에 출력된다)
alert('CS4'.match(/CS.4/)); // null, 점과 일치하는 문자가 없기 때문에s플래그와 점을 사용하여 모든 문자 찾기
- 기본적으로 점은
\n과 일치하지 않음 pattern:s를 사용하면 점은 모든 문자와 일치
alert('A\nB'.match(/A.B/)); // null
alert('A\nB'.match(/A.B/s)); // A\nB유니코드 : u플래그와 \p{…}클래스
-
pattern:u플래그로 정규 표현식에서 유니코드 기능을 활성화할 수 있다.- 4바이트 문자를 2바이트 문자 2개로 처리하지 않고 문자 한 개로 올바르게 처리한다.
\p{…}를 이용하여 유니코드 프로퍼티를 검색에 사용할 수 있다.
-
유니코드 프로퍼티를 사용하면 특정 단어의 단어, 따옴표나 통화 단위같은 특수 문자 등을 모두 검색할 수 있다.
-
자바스크립트는 문자열에 유니코드 인코딩을 사용한다.
- 대부분의 문자는 2바이트로 인코딩되어 있는데, 이것으로는 65,536개 까지만 표현할 수 있다. 따라서 일부 문자는 4바이트로 인코딩되어있다.
-
문자는 하나인데 길이가 2가 나오는 경우
-
length는 4바이트 문자를 2바이트 문자 2개로 취급. 4바이트를 하나로 묶어서 취급해야 하므로 올바르지 않은 결과이다. (서로게이트 쌍)
alert('😄'.length); // 2
alert('𝒳'.length); // 2-
기본적으로는 정규표현식도 4바이트의 긴 문자를 2바이트 문자 2개로 취급한다. 문자열의 경우처럼 이런 방식은 잘못된 결과로 이어질 수 있다.
-
문자열과 다르게 정규표현식에는 이런 문제를 해결할 수 있는
pattern:u플래그가 있다. 이를 사용하면 유니코드 프로퍼티를 사용한 검색이 가능해진다. -
pattern:\p{…}를 사용하면 프로퍼티를 통해 문자를 찾을 수 있다. 이를 사용하기 위해서는 정규 표현식에pattern:u플래그가 반드시 있어야 한다.
let str = 'A ბ ㄱ';
alert(str.match(/\p{L}/gu)); // A,ბ,ㄱ
alert(str.match(/\p{L}/g)); // null ('u' 플래그가 없어서 일치 결과 없음)-
다음은 주요 문자 범주와 각각의 하위 범주 목록
-
문자(Letter)
L- 소문자(lowercase)
Ll - 조정(modifier)
Lm - 단어의 첫글자를 대문자로(titlecase)
Lt - 대문자(uppercase)
Lu - 기타(other)
Lo
- 소문자(lowercase)
-
숫자(Number)
N- 10진수(decimal digit)
Nd - 문자(letter number)
Nl - 기타(other)
No
- 10진수(decimal digit)
-
문장 부호(Punctuation)
P- 연결선(connector)
Pc - 대시(dash)
Pd - 처음 따옴표(initial quote)
Pi - 마지막 따옴표(final quote)
Pf - 열기(open)
Ps - 닫기(close)
Pe - 기타(other)
Po
- 연결선(connector)
-
표시(Mark)
M(강세 등)- 간격 결합(spacing combining)
Mc - 묶음(enclosing)
Me - 비공백(non-spacing)
Mn
- 간격 결합(spacing combining)
-
기호(Symbol)
S- 통화(currency)
Sc - 수정(modifier)
Sk - 수학(math)
Sm - 기타(other)
So
- 통화(currency)
-
구분 기호(Separator)
Z- 줄(line)
Zl - 단락(paragraph)
Zp - 공백(space)
Zs
- 줄(line)
-
기타(other)
C- 제어(control)
Cc - 형식(format)
Cf - 할당되지 않음(not assigned)
Cn - 사용자 지정(private use)
Co - 서로게이트(surrogate)
Cs
- 제어(control)
-
소문자를 찾을 때
pattern:\p{Ll}, 문장부호를 찾을 때pattern:\p{P}등으로 검색할 수 있다. -
참고할 수 있는 문서
앵커 : 문자열의 시작 ^과 끝 $
- 캐럿(caret) 기호
pattern:^와 달러기호pattern:$는 정규식에서 앵커라는 뜻을 지닌다. - 캐럿기호는 텍스트의 시작, 달러기호는 텍스트의 끝을 나타낸다.
// ^Mary ==> 문자열이 Mary로 시작하는지 검사
// snow$ ==> 문자열이 snow로 끝나는지 검사
let str = 'Mary and a little lamb';
alert(/snow$/.test(str)); // truepattern:^…$는 문자열이 패턴과 완전히 일치하는지 확인할 때 자주 사용된다. 사용자 입력 내용이 올바른 형식으로 되어있는지 확인할 때가 대표적인 예- 문자열 전체가 이 형식에 일치해야 한다. 형식에서 벗어난 문자가 있거나 문자가 더 많으면 false를 출력한다.
let goodInput = '12:34';
let badInput = '12:345';
let regexp = /^\d\d:\d\d$/;
alert(regexp.test(goodInput)); // true
alert(regexp.test(badInput)); // falsem플래그
pattern:m플래그를 사용하면 여러 행 모드(multiline mode)를 활성화할 수 있음- 여러 행 모드는
pattern:^,pattern:$의 작동방식에만 영향을 준다. - 전체 문자열의 처음/끝 뿐만아니라 각 행의 시작/끝에도 대응한다.
let str = `1st place: Winnie
2nd place: Piglet
3rd place: Eeyore`;
alert(str.match(/^\d/gm)); // 1, 2, 3
alert(str.match(/^\d/g)); // 1 , m플래그가 없으면 맨 앞 숫자만 검색된다.
let str = `Winnie: 1
Piglet: 2
Eeyore: 3`;
alert(str.match(/\d$/gm)); // 1,2,3- 줄 바꿈을 찾을 때
pattern:^,pattern:$뿐만아니라\n도 사용할 수 있다.
let str = `Winnie: 1
Piglet: 2
Eeyore: 3`;
alert(str.match(/\d\n/gm)); // 1,2
/*
3뒤에는 줄바뀜문자가 없어서 미출력됨.
*/정규식에서 쓰이는 메서드
-
exec
- 대응되는 문자열을 찾는 RegExp 메서드
- 대응되는 문자열을 찾으면 정보를 갖고있는 배열을 반환, 찾지 못하면 null 을 반환
-
test
- 대응되는 문자열이 있는지 검사하는 RegExp 메서드
- 대응되는 문자열을 찾으면 true, 아니면 false를 반환
-
match
- 대응되는 문자열을 찾는 String 메서드
- 대응되는 문자열을 찾으면 갖고있는 배열을 반환, 찾지 못하면 null을 반환
-
search
- 대응되는 문자열이 있는 검사하는 String 메서드
- 대응된 부분의 인덱스를 반환, 찾지 못하면 -1을 반환
-
replace
- 대응되는 문자열을 찾아 다른 문자열로 치환하는 String 메서드
-
split
- 정규식 혹은 문자열로 대상 문자열로 나누어 배열로 반환하는 String 메서드
정규식 검색 기준 패턴
- | : OR.
a|b식으로 사용 - [] : 괄호안의 문자들중 하나. or 처리 묶음
/[abc]/: a or b or c 를 포함하는[다-바]: 다 or 라 or 마 or 바
- [^문자] : 괄호안의 문자를 제외한 것
[^lgen]‘l’ ‘g’ ‘E’ ‘n’ 4개 문자를 제외
- ^문자열 : 특정 문자열로 시작
/^www/
- 문자열$ : 특정 문자열로 끝남
/com$/
정규표현식 수량 패턴
-
어떠한 패턴이 얼만큼 등장하는지
-
*: 0개 이상 나타나는 문자a*b: a가 앞에 있을 수도 있고, 여러개 있을 수도 있고 b도 뒤에 있을 수도 있고, 여러 개 있을 수도 있음. ‘aab’,‘ab’ 모두 가능하다
-
+: 1개 이상 나타나는 문자a+b: a가 한개이상, b도 한개 이상 있어야한다. ‘ab’, ‘aabb’, ‘abb’ ..
-
?: 없거나 1개인 경우a?b: a가 없거나 1개, b가 없거나 1개. ‘b’, ‘ab’..
-
{m,n}: m회 이상 n회 이하 나타나는 문자[els]{1,3}: e or l or s 가 1개 이상 3개 이하